package client

import (
	. "chess_platform/internal/common"
	"chess_platform/models/client"
	"chess_platform/models/pc"
	"math/rand"
	"time"
)

//[client]抽奖系统
type LotteryController struct {
	GrantController
}

func (b *LotteryController) URLMapping() {
	b.Mapping("ListLotteryProduct", b.ListLotteryProduct)
	b.Mapping("ListLotteryExchange", b.ListLotteryExchange)
	b.Mapping("BuyLotteryCount", b.BuyLotteryCount)
	b.Mapping("DrawLottery", b.DrawLottery)
}

// @Title 抽奖奖品列表
// @Description 抽奖奖品列表
// @Success 0 {object} [] 奖品列表
// @router /list-lottery-product [post]
func (b *LotteryController) ListLotteryProduct() {
	data, err := client.ListLotteryProduct()
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 钻石兑换抽奖次数列表
// @Description 钻石兑换抽奖次数列表
// @Success 0 {object} [] 奖品列表
// @router /list-lottery-exchange [post]
func (b *LotteryController) ListLotteryExchange() {
	data, err := client.ListLotteryExchange()
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	b.Res.Data = data
	b.ResponseSuccess()
}

// @Title 用钻石购买抽奖次数
// @Description 用钻石购买抽奖次数
// @Param  id   body    int true      "钻石兑换抽奖次数表的id"
// @Success 0 {object} [] 奖品列表
// @router /buy-lottery-count [post]
func (b *LotteryController) BuyLotteryCount() {
	type Params struct {
		Id int64 `json:"id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}
	/*
		0. 读出钻石购买抽奖次数的表
		1. 判断用户是否足够的钻石购买
		2. 把抽奖次数加到user_attr里lottery_count字段里
		3. 加上购买记录
	*/
	//0. 读出钻石购买抽奖次数的表
	ex, err := pc.LotteryExchangeById(p.Id)
	if err != nil {
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if ex.Id == 0 {
		b.ResponseFail("您要兑换的抽奖次数项不存在")
		return
	}
	//1. 钻石是否足够
	ok := client.ChangeAccountValueFromLobby(b.Uid, -ex.Diamond,
		0, 0, ACCTRAN_OPER_TYPE_Exchange, 0)
	if !ok {
		b.ResponseFail("钻石不足,请您充值")
		return
	}
	//下面情况是钻石足够

	//rollback
	rollback := func() {
		client.ChangeAccountValueFromLobby(b.Uid, ex.Diamond,
			0, 0, ACCTRAN_OPER_TYPE_Exchange, 0)
	}
	o := NewDBOrm(DBChess)
	o.Begin()
	defer o.Rollback()

	//2. 把抽奖次数加到user_attr里lottery_count字段里
	_, err = client.UpdateLotteryCount(b.Uid, ex.LotteryCount, o)
	if err != nil {
		o.Rollback()
		rollback()
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	//3. 加上购买记录
	_, err = client.NewLotteryConsumeRecord(b.Uid, ex.Diamond, ex.LotteryCount, o)
	if err != nil {
		o.Rollback()
		rollback()
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
}

// @Title 抽奖
// @Description 抽奖
// @Success 0 {object} [] 奖品列表
// @router /draw-lottery [post]
func (b *LotteryController) DrawLottery() {
	/*
		1. 判断抽奖次数是否足够,如果足够,往下执行
		2. 减少抽奖次数,user_attr表里lottery_count字段的值减少1
		3. 获取每个奖品的概率及piece,获取当前玩家拥有各个奖品的piece
	*/
	//1. 判断抽奖次数是否足够,如果足够,往下执行
	//2. 减少抽奖次数,user_attr表里lottery_count字段的值减少1
	o := NewDBOrm(DBChess)
	o.Begin()
	defer o.Rollback()
	n, err := client.UpdateLotteryCount(b.Uid, -1, o)
	if err != nil {
		o.Rollback()
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	if n == 0 {
		o.Rollback()
		b.Res.Count = ErrLotteryNotEnough
		b.Res.Msg = "抽奖次数不足"
		b.Response()
	}

	//3. 获取每个奖品的概率及piece,获取当前玩家拥有各个奖品的piece
	product, err := client.ListLotteryProduct()
	if err != nil {
		o.Rollback()
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}

	//获取玩家的奖品列表
	userProduct, err := client.ListLotteryUser(b.Uid)
	if err != nil {
		o.Rollback()
		LogClient.Error(b.DatabaseError(err.Error()))
		return
	}
	for _, v := range product {
		print(v.Id)
	}
	for _, v := range userProduct {
		print(v.Uid)
	}

	o.Commit()
	b.ResponseSuccess()
}

//按权重抽奖结构体
type LotteryDraw struct {
	Id     int64
	Weight int
}

//把每个奖品的概率转为权重
func ConvertProduct(p []LotteryProduct, up []LotteryUser) []LotteryDraw {
	var ld []LotteryDraw
	return ld
}

//按权重抽奖
func Draw(ld []LotteryDraw) LotteryDraw {

	var totalWeigh int
	for _, v := range ld {
		totalWeigh += v.Weight
	}
	println("totalWeight:", totalWeigh)
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	curWeight := r.Intn(totalWeigh)
	var luckDraw LotteryDraw
	for _, v := range ld {
		if curWeight < v.Weight {
			luckDraw = v
			break
		}
		curWeight -= v.Weight
	}
	return luckDraw
}
